package cn.gson.financial.kernel.service.impl;


import cn.gson.financial.kernel.common.DateUtil;
import cn.gson.financial.kernel.common.DoubleValueUtil;
import cn.gson.financial.kernel.constans.ComprehensiveParamesConstans;
import cn.gson.financial.kernel.exception.ServiceException;
import cn.gson.financial.kernel.model.entity.*;
import cn.gson.financial.kernel.model.entity.Currency;
import cn.gson.financial.kernel.model.mapper.*;
import cn.gson.financial.kernel.model.vo.*;
import cn.gson.financial.kernel.service.SubjectService;
import cn.gson.financial.kernel.utils.BaseUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.AllArgsConstructor;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

@Slf4j
@Service
@AllArgsConstructor
public class SubjectServiceImpl extends ServiceImpl<SubjectMapper, Subject> implements SubjectService {

    private AccountSetsMapper accountSetsMapper;
    private VoucherMapper voucherMapper;
    private SubjectMapper subjectMapper;
    private VoucherDetailsMapper voucherDetailsMapper;
    private VoucherTemplateDetailsMapper voucherTemplateDetailsMapper;
    private ComprehensiveParamsMapper comprehensiveParamsMapper;

    @Override
    public int batchInsert(List<Subject> list) {
        return baseMapper.batchInsert(list);
    }

    @Override
    public List<SubjectVo> selectData(Wrapper<Subject> queryWrapper, boolean showAll) {
        QueryWrapper<Subject> qw = (QueryWrapper<Subject>) queryWrapper;
        qw.eq("status", 1);
        Map<Integer, Subject> subjectMap = baseMapper.selectList(qw).stream().collect(Collectors.toMap(Subject::getId, subject -> subject));
        List<Subject> list = baseMapper.selectNoChildrenSubject(qw);

        list.forEach(subject -> {
            if (subject.getLevel() != 1) {
                recursiveChildren(subjectMap, subject, subject.getParentId());
            }
        });

        if (showAll) {
            list.forEach(subject -> subjectMap.remove(subject.getId()));
            list.addAll(subjectMap.values());
        }

        List<SubjectVo> collect = list.stream().sorted(Comparator.comparing(Subject::getCode)).map(subject -> {
            SubjectVo vo = new SubjectVo();
            BeanUtils.copyProperties(subject, vo);
            return vo;
        }).collect(Collectors.toList());

        return collect;
    }
    /**
     * 明细科目
     *
     * @param accountDate
     * @param accountSetsId
     * @return
     */
    @Override
    public List<Subject> accountBookList(Date accountDate, Integer accountSetsId, boolean showNumPrice) {
//        List<Subject> subjectList = baseMapper.selectAccountBookList(accountDate != null ? DateUtil.getMonthEnd(accountDate) : null, accountSetsId, showNumPrice);
        Date date = accountDate != null ? DateUtil.getMonthEnd(accountDate) : null;
        String param;
        if (date == null){
            param = null;
        }else {
            param = new SimpleDateFormat("yyyyMM").format(date);
        }

        List<Subject> subjectList = baseMapper.selectAccountBookList(param, accountSetsId, showNumPrice);
        System.out.println(subjectList);
        Map<Integer, Subject> temp = new HashMap<>();
        subjectList.forEach(subject -> this.recursiveParent(temp, subject));
        return temp.values().stream().sorted(Comparator.comparing(Subject::getCode)).distinct().collect(Collectors.toList());
    }

    @Override
    public List<Subject> accountBookListCurrency(Date startTime,Date endTime, Integer accountSetsId, boolean showNumPrice, Integer currencyId) {
        List<Subject> subjectList;
        if (currencyId == -1){
           subjectList = baseMapper.selectAccountBookSubjectSummaryList(startTime,endTime, accountSetsId, showNumPrice);
        }else if(currencyId == -2){
           subjectList = baseMapper.selectAccountBookListBaseCurrency(startTime,endTime, accountSetsId, showNumPrice);
        }else {
           subjectList = baseMapper.selectAccountBookListCurrency(startTime,endTime, accountSetsId, showNumPrice, currencyId);
        }
        Map<Integer, Subject> temp = new HashMap<>();
        subjectList.forEach(subject -> this.recursiveParent(temp, subject));
        return temp.values().stream().sorted(Comparator.comparing(Subject::getCode)).distinct().collect(Collectors.toList());
    }

    @Override
    public List<Subject> accountBookList1(SubjectSelectVo vo, Integer accountSetsId, boolean showNumPrice) {
        Date date1 = new Date();
        Date date2 = new Date();
        try {
            date1 = new SimpleDateFormat("yyyy-MM").parse(vo.getTimeStart());
            date2 = new SimpleDateFormat("yyyy-MM").parse(vo.getTimeEnd());
        } catch (ParseException e) {
            e.printStackTrace();
        }
        System.out.println(vo);
         date1=DateUtil.getMonthBegin(date1);
         date2=DateUtil.getMonthEnd(date2);
        String subjectIdStart=(vo.getSubjectIdStart()!=null)?vo.getSubjectIdStart():accountSetsMapper.selectSubjectFrist(accountSetsId);
        String subjectIdEnd=(vo.getSubjectIdEnd()!=null)?vo.getSubjectIdEnd():accountSetsMapper.selectSubjectEnd(accountSetsId);
        Short levelStart=vo.getLevelStart();
        Short levelEnd=vo.getLevelEnd();
        Integer id = null;
        List<Subject> subjectList;
        if (vo.getCurrencyId()==-1){
            subjectList = baseMapper.selectAccountBookList1(date1,date2,subjectIdStart,subjectIdEnd,levelStart,levelEnd, accountSetsId, showNumPrice,id);
        }else if (vo.getCurrencyId()==-2){
            subjectList = baseMapper.selectAccountBookList2(date1,date2,subjectIdStart,subjectIdEnd,levelStart,levelEnd, accountSetsId, showNumPrice);
        }else{
            subjectList = baseMapper.selectAccountBookList1(date1,date2,subjectIdStart,subjectIdEnd,levelStart,levelEnd, accountSetsId, showNumPrice,vo.getCurrencyId());
        }
        System.out.println(subjectList);
//        subjectList = recursiveSubjectBalance(subjectList);
        Map<Integer, Subject> temp = new HashMap<>();
        subjectList.forEach(subject -> this.recursiveParent(temp, subject));
        System.out.println("subjectList"+subjectList);
        subjectList = recursiveSubjectBalance(temp.values().stream().sorted(Comparator.comparing(Subject::getCode)).distinct().collect(Collectors.toList()));
        if (subjectList.size()>0){
            for (int i = 0; i < subjectList.size(); i++) {
                if (subjectList.get(i).getLevel()<levelStart || subjectList.get(i).getLevel()>levelEnd){
                    subjectList.remove(i);
                    i--;
                }
            }
        }
//        return temp.values().stream().sorted(Comparator.comparing(Subject::getCode)).distinct().collect(Collectors.toList());
        return subjectList;
    }
    @Override
    public List<Currency> accountBookCurrencyList(Integer accountSetsId) {
        List<Currency> currencyList = baseMapper.accountBookCurrencyList(accountSetsId);
        for (int i = 0; i < currencyList.size(); i++) {
            if (currencyList.get(i).getName().equals("人民币")){
                currencyList.remove(i);
                i--;
            }
        }
        System.out.println(currencyList);
        return currencyList;
    }

    //总账动态 查询
    @Override
    public List<Subject> accountBookListByParam(String startTime,String endTime ,String startSubject, String endSubject, Integer startLevel, Integer endLevel,Integer accountSetsId,boolean isOpen,boolean showNumPrice,Integer currencyId) {
        List<Subject> subjectList = baseMapper.selectAccountBookListByParam(startTime, endTime, startSubject, endSubject, startLevel, endLevel, accountSetsId,showNumPrice, currencyId);
        subjectList.forEach(System.out::println);
        //        return subjectList;
        if(!isOpen){ //是否开启 查询 科目的 父科目
            return  subjectList;
        }
        Map<Integer, Subject> temp = new HashMap<>();
        subjectList.forEach(subject -> this.recursiveParent(temp, subject));
        return temp.values().stream().sorted(Comparator.comparing(Subject::getCode)).distinct().collect(Collectors.toList());
    }

    /**
     * 余额明细科目
     *
     * @param accountDate
     * @param accountSetsId
     * @return
     */
    @Override
    public List<Subject> balanceSubjectList(Date accountDate, Integer accountSetsId, boolean showNumPrice) {
        List<Subject> subjectList = this.accountBookList(DateUtil.getMonthEnd(accountDate), accountSetsId, showNumPrice);

        Map<Integer, Subject> temp = new HashMap<>();
        subjectList.forEach(subject -> this.recursiveParent(temp, subject));
        return temp.values().stream().sorted(Comparator.comparing(Subject::getCode)).distinct().collect(Collectors.toList());
    }

    @Override
    @Transactional
    public void importVoucher(List<SubjectVo> voucherList, AccountSets accountSets) {
        AtomicInteger update = new AtomicInteger(0);
        AtomicInteger insert = new AtomicInteger(0);
        this.recursive(voucherList, update, insert, accountSets);
    }

    @Override
    public InitBlanceVo findBySubIdAndAccountSwtId(Integer subId, Integer accountSetId) {
//        return subjectMapper.findBySubIdAndAccountSwtId(subId, accountSetId);
        return null;
    }

    @Override
    public boolean saveInitBlanceVo(InitBlanceVo vo) {
        int x = subjectMapper.saveInitBlanceVo(vo);
        if(x > 0){
            return true;
        }
        return false;
    }
    @Override
    public boolean updateInitBlanceVo(InitBlanceVo vo){
        int x = subjectMapper.updateInitBlanceVo(vo);
        if(x > 0){
            return true;
        }
        return false;
    }

    @Override
    public List<VoucherDetails> findBySubId(List<Integer> subjectIdList) {
        return subjectMapper.findBySubId(subjectIdList);
    }

    @Override
    public List<Subject> findByTypeCurrency(Integer accountSetsId, String type, Integer currencyId) {
        return subjectMapper.findByTypeCurrency(accountSetsId,type,currencyId);

    }

    @Override
    public int updateSubject(Integer subjectId) {
        return subjectMapper.updateSubject(subjectId);
    }

    private void recursive(@NonNull List<SubjectVo> voucherList, AtomicInteger update, AtomicInteger insert, AccountSets accountSets) {
        for (SubjectVo vo : voucherList) {
            if (vo.getId() != null) {
                if (this.checkUse(vo.getId())) {
                    continue;
                }

                this.updateById(vo);
                update.incrementAndGet();
                if (!vo.getChildren().isEmpty()) {
                    vo.getChildren().forEach(s -> s.setParentId(vo.getId()));
                    this.recursive(vo.getChildren(), update, insert, accountSets);
                }
            } else {
                if (accountSets.getAccountingStandards() == (short) 0 && vo.getLevel() == (short) 1) {
                    continue;
                }

                //一般纳税人
                this.save(vo);
                insert.incrementAndGet();
                if (!vo.getChildren().isEmpty()) {
                    vo.getChildren().forEach(s -> s.setParentId(vo.getId()));
                    this.recursive(vo.getChildren(), update, insert, accountSets);
                }
            }
        }
    }

    /**
     * 科目余额
     *
     * @param accountDate
     * @param accountSetsId
     * @return
     */
    @Override
    public List<BalanceVo> subjectBalance(Date accountDate, Integer accountSetsId, boolean showNumPrice) {
        //当前查询账套
        AccountSets accountSets = accountSetsMapper.selectById(accountSetsId);
        List<Subject> subjects = this.accountBookList(null, accountSetsId, showNumPrice);
        //转换为余额对象
        Map<Integer, BalanceVo> sbvMap = subjects.stream().collect(Collectors.toMap(Subject::getId, subject -> {
            BalanceVo sbv = new BalanceVo();
            sbv.setSubjectId(subject.getId());
            sbv.setCode(subject.getCode());
            sbv.setParentId(subject.getParentId());
            sbv.setName(subject.getName());
            sbv.setLevel(subject.getLevel());
            sbv.setUnit(subject.getUnit());
            sbv.setBalanceDirection(subject.getBalanceDirection().toString());
            return sbv;
        }));

        //原始期初余额
        if (sbvMap.isEmpty()) {
            return new ArrayList<>();
        }


        //对比账套时间，判断是否是初始账套时间
        if (!DateFormatUtils.format(accountSets.getEnableDate(), "yyyyMM").equals(DateFormatUtils.format(accountDate, "yyyyMM"))) {
            List<VoucherDetailVo> details = voucherMapper.selectSubjectDetail(sbvMap.keySet(), accountSetsId, DateUtil.getMonthBegin(accountDate), null, showNumPrice);
            details.forEach(vd -> {
                if (sbvMap.containsKey(vd.getSubjectId())) {
                    BalanceVo sbv = sbvMap.get(vd.getSubjectId());
                    Double val = null;
                    switch (sbv.getBalanceDirection()) {
                        case "借":
                            val = DoubleValueUtil.getNotNullVal(vd.getDebitAmount()) - DoubleValueUtil.getNotNullVal(vd.getCreditAmount());
                            break;
                        case "贷":
                            val = DoubleValueUtil.getNotNullVal(vd.getCreditAmount()) - DoubleValueUtil.getNotNullVal(vd.getDebitAmount());
                            break;
                    }
                    sbv.setBeginningActiveBalance(val);
                }
            });
        } else {
            LambdaQueryWrapper<VoucherDetails> qwi = Wrappers.lambdaQuery();
            qwi.eq(VoucherDetails::getAccountSetsId, accountSetsId);
            qwi.in(VoucherDetails::getSubjectId, sbvMap.keySet());
            qwi.isNull(VoucherDetails::getVoucherId);
            qwi.and(wrapper -> {
                wrapper.or(true).isNotNull(VoucherDetails::getCreditAmount);
                wrapper.or(true).isNotNull(VoucherDetails::getDebitAmount);
                return wrapper;
            });
            this.voucherDetailsMapper.selectList(qwi).forEach(ib -> {
                if (sbvMap.containsKey(ib.getSubjectId())) {
                    sbvMap.get(ib.getSubjectId()).setBeginningBalance(DoubleValueUtil.getNotNullVal(ib.getCreditAmount(), ib.getDebitAmount()));
                }
            });
        }

        //本期发生额
        List<VoucherDetailVo> details = voucherMapper.selectSubjectDetail(sbvMap.keySet(), accountSetsId, DateUtil.getMonthBegin(accountDate), DateUtil.getMonthEnd(accountDate), showNumPrice);
        details.forEach(vd -> {
            if (sbvMap.containsKey(vd.getSubjectId())) {
                BalanceVo sbv = sbvMap.get(vd.getSubjectId());
                sbv.setCurrentCreditAmount(vd.getCreditAmount());
                sbv.setCurrentDebitAmount(vd.getDebitAmount());
                if (showNumPrice && vd.getBalanceDirection() != null) {
                    switch (vd.getBalanceDirection()) {
                        case "借":
                            sbv.setCurrentDebitAmountNum(vd.getNum());
                            break;
                        case "贷":
                            sbv.setCurrentCreditAmountNum(vd.getNum());
                            break;
                    }
                }
            }
        });

        //合计
        BalanceVo aCombined = new BalanceVo();
        aCombined.setName("合计");
        //计算期末
        List<BalanceVo> balanceVos = sbvMap.values().stream().sorted(Comparator.comparing(BalanceVo::getCode)).collect(Collectors.toList());
        for (BalanceVo vo : balanceVos) {
            //期初
            Double bb = DoubleValueUtil.getNotNullVal(vo.getBeginningBalance());
            //本期借贷金额
            Double cc = DoubleValueUtil.getNotNullVal(vo.getCurrentCreditAmount());
            Double cd = DoubleValueUtil.getNotNullVal(vo.getCurrentDebitAmount());
            //本期借贷数量
            Double ccNum = DoubleValueUtil.getNotNullVal(vo.getCurrentCreditAmountNum());
            Double cdNum = DoubleValueUtil.getNotNullVal(vo.getCurrentDebitAmountNum());

            //根据方向计算余额
            switch (vo.getBalanceDirection()) {
                case "借":
                    vo.setEndingActiveBalance(bb + cd - cc);
                    break;
                case "贷":
                    vo.setEndingActiveBalance(bb - cd + cc);
                    break;
            }

            if (showNumPrice) {
                switch (vo.getBalanceDirection()) {
                    case "借":
                        vo.setEndingDebitBalanceNum(cdNum - ccNum);
                        break;
                    case "贷":
                        vo.setEndingCreditBalanceNum(ccNum - cdNum);
                        break;
                }
            }

            //计算合计列
            aCombined.setBeginningCreditBalance(vo.getBeginningCreditBalance());
            aCombined.setBeginningDebitBalance(vo.getBeginningDebitBalance());

            aCombined.setCurrentCreditAmount(vo.getCurrentCreditAmount());
            aCombined.setCurrentCreditAmountNum(vo.getCurrentCreditAmountNum());
            aCombined.setCurrentDebitAmount(vo.getCurrentDebitAmount());
            aCombined.setCurrentDebitAmountNum(vo.getCurrentDebitAmountNum());

            aCombined.setEndingCreditBalance(vo.getEndingCreditBalance());
            aCombined.setEndingCreditBalanceNum(vo.getEndingCreditBalanceNum());
            aCombined.setEndingDebitBalance(vo.getEndingDebitBalance());
            aCombined.setEndingDebitBalanceNum(vo.getEndingDebitBalanceNum());
        }

        //计算父节点
        for (int i = balanceVos.size() - 1; i > 0; i--) {
            BalanceVo vo = balanceVos.get(i);
            if (vo.getLevel() != 1) {
                BalanceVo parent = sbvMap.get(vo.getParentId());
                if (parent != null) {
                    parent.setBeginningBalance(vo.getBeginningBalance());
                    parent.setCurrentDebitAmount(vo.getCurrentDebitAmount());
                    parent.setCurrentDebitAmountNum(vo.getCurrentDebitAmountNum());
                    parent.setCurrentCreditAmount(vo.getCurrentCreditAmount());
                    parent.setCurrentCreditAmountNum(vo.getCurrentCreditAmountNum());
                    if (vo.getEndingCreditBalance() != null) {
                        parent.setEndingCreditBalance(vo.getEndingCreditBalance());
                    }
                    if (vo.getEndingDebitBalance() != null) {
                        parent.setEndingCreditBalance(vo.getEndingDebitBalance());
                    }
                }
            }
        }

        if (balanceVos.size() > 0) {
            //过滤掉空行
            balanceVos = balanceVos.stream().filter(vo ->
                    (vo.getBeginningBalance() != null && vo.getBeginningBalance() != 0) ||
                            (vo.getEndingBalance() != null && vo.getEndingBalance() != 0) ||
                            (vo.getCurrentDebitAmount() != null && vo.getCurrentDebitAmount() != 0) ||
                            (vo.getCurrentCreditAmount() != null && vo.getCurrentCreditAmount() != 0)
            ).collect(Collectors.toList());
            balanceVos.add(aCombined);
        }

        return balanceVos;
    }




    /**
     * 科目余额 改 动态查询
     *
     * @param
     * @param accountSetsId
     * @return
     */
    @Override
    public List<BalanceVo> subjectBalanceByParam(String startTime,String endTime ,String startSubject, String endSubject, Integer startLevel, Integer endLevel,Integer accountSetsId,boolean showNumPrice,boolean isOpen,Integer currencyId) {
        //当前查询账套
        //1.查询动态之后的科目（断）
        //2.补充所有的父级科目
        //3.查询每个科目的期初、其中和期末
        //4.相加所有1级科目-->累计
        //5.判断删除第一个父级科目（断）
//        AccountSets accountSets = accountSetsMapper.selectById(accountSetsId);
        List<Subject> subjects = this.selectAccountList(startTime, endTime, startSubject, endSubject, startLevel, endLevel, accountSetsId,isOpen,showNumPrice,currencyId);
        if (currencyId == -1){
            currencyId = null;
        }
        subjects = recursiveSubjectBalance(subjects);
        List<Integer> subjectIds = new ArrayList<>();
        List<String> subjectCodes = new ArrayList<>();
        List<Short> levels = new ArrayList<>();
        for (int i = 0; i <subjects.size() ; i++) {
            subjectCodes.add(subjects.get(i).getCode());
            subjectIds.add(subjects.get(i).getId());
            levels.add(subjects.get(i).getLevel());
            if (startSubject!=null && !startSubject.equals("")){
                if (subjects.get(i).getCode().equals(startSubject.substring(0,4))){
                    subjects.remove(i);
                    i--;
                }
            }
        }

        Short levelMin = levels.stream().min(Comparator.comparing(x -> x)).orElse(null);
        System.out.println("level==============================="+levelMin);
        //转换为余额对象
        Map<String, BalanceVo> sbvMap = subjects.stream().collect(Collectors.toMap(Subject::getCode, subject -> {
            BalanceVo sbv = new BalanceVo();
            sbv.setSubjectId(subject.getId());
            sbv.setCode(subject.getCode());
            sbv.setParentId(subject.getParentId());
            sbv.setName(subject.getName());
            sbv.setLevel(subject.getLevel());
            sbv.setUnit(subject.getUnit());
            sbv.setBalanceDirection(subject.getBalanceDirection().toString());
            sbv.setCurrencyAccounting(subject.getCurrencyAccounting());
            sbv.setIsAuxiliary(subject.getIsAuxiliary());
            System.out.println("sbv: " + sbv);
            return sbv;
        }));
        System.out.println("----------------------------");
        //原始期初余额
        if (sbvMap.isEmpty()) {
            return new ArrayList<>();
        }

//        String jie = comprehensiveParamsMapper.queryDefaultContent(ComprehensiveParamesConstans.JIE);
//        String dai = comprehensiveParamsMapper.queryDefaultContent(ComprehensiveParamesConstans.DAI);

        //对比账套时间，判断是否是初始账套时间
//        Date st = cn.gson.financial.kernel.utils.DateUtil.parseDate(startTime);
//        int year = cn.gson.financial.kernel.utils.DateUtil.getYear(st);
//        int mon = cn.gson.financial.kernel.utils.DateUtil.getMonth(st);
//        String m = "";
//        int k = 1;
        List<InitBlanceVo> initBlanceVos = new ArrayList<>();
        if(subjects.size()!=0){
            for (int i = 0; i < subjects.size(); i++) {
                InitBlanceVo initBlanceVo = new InitBlanceVo();
                initBlanceVo.setSubjectCode(subjects.get(i).getCode());
                initBlanceVo.setSubjectName(subjects.get(i).getName());
                initBlanceVo.setSubjectId(subjects.get(i).getId());
                initBlanceVo.setBalanceDirection(subjects.get(i).getBalanceDirection().toString());
                InitBlanceVo initBlanceVoAmount = this.subjectMapper.selectInitBalanceVo(accountSetsId, startTime,subjects.get(i).getCode(),currencyId);
                System.out.println(initBlanceVoAmount);
                if (initBlanceVoAmount!=null){
                    if (initBlanceVoAmount.getEndingCreditBalence() == null){
                        initBlanceVo.setEndingDebitBalance(initBlanceVoAmount.getEndingDebitBalance());
                    }else if(initBlanceVoAmount.getEndingDebitBalance() == null) {
                        initBlanceVo.setEndingCreditBalence(initBlanceVoAmount.getEndingCreditBalence());
                    }else {
                        initBlanceVo.setEndingDebitBalance(initBlanceVoAmount.getEndingDebitBalance());
                        initBlanceVo.setEndingCreditBalence(initBlanceVoAmount.getEndingCreditBalence());
                    }
                    initBlanceVos.add(initBlanceVo);
                }
                if (initBlanceVoAmount!=null){
                    if (initBlanceVoAmount.getCumulativeCreditNum() != null){
                        initBlanceVo.setEndingCreditBalenceNum(initBlanceVoAmount.getCumulativeCreditNum());
                    }
                    if (initBlanceVoAmount.getCumulativeDebitNum() != null) {
                        initBlanceVo.setEndingDebitBalanceNum(initBlanceVoAmount.getCumulativeDebitNum());
                    }
                    if (initBlanceVoAmount.getCurrencyEndingCreditBalance() != null){
                        initBlanceVo.setCurrencyEndingCreditBalance(initBlanceVoAmount.getCurrencyEndingCreditBalance());
                    }
                    if(initBlanceVoAmount.getCurrencyEndingDebitBalance() != null) {
                        initBlanceVo.setCurrencyEndingDebitBalance(initBlanceVoAmount.getCurrencyEndingDebitBalance());
                    }
                }
            }
        }

//        while (true){
//            if((mon-k)<10){
//                m = "0,"+(mon-k);
//            }
//            if(mon == 1){
//                year = year-1;
//                m = 12+"";
//            }
//
//            String time = year+"-"+m;
//            time = time.replace(",", "");
//        if (subjects.size()!=0){
//            for (int i = 0; i < subjects.size(); i++) {
//                InitBlanceVo initBlanceVo = this.subjectMapper.selectInitBalanceVo(accountSetsId, startTime,subjects.get(i).getCode());
//                if (initBlanceVo!=null){
//                    initBlanceVos.add(initBlanceVo);
//                }
//
//            }
//        }
        System.out.println(initBlanceVos);

//            if(initBlanceVos.size() != 0 || k == 12){
//                break;
//            }
//            k++;
//        }
        //对比账套时间，判断是否是初始账套时间
//        if (!DateFormatUtils.format(accountSets.getEnableDate(), "yyyyMM").equals(DateFormatUtils.format(BaseUtil.strToDate(startTime, "yyyy-MM-dd"), "yyyyMM")) && initBlanceVos.size() != 0) {
            initBlanceVos.forEach(ib -> {
                if (sbvMap.containsKey(ib.getSubjectCode())) {
                    System.out.println(ib);
                    if (ib.getBalanceDirection().equals("借")){
                        Double a = DoubleValueUtil.getNotNullVal(ib.getEndingDebitBalance())-DoubleValueUtil.getNotNullVal(ib.getEndingCreditBalence());
//                        if (a>=0){
                            sbvMap.get(ib.getSubjectCode()).setBeginningBalance(DoubleValueUtil.getNotNullVal(ib.getEndingDebitBalance())-DoubleValueUtil.getNotNullVal(ib.getEndingCreditBalence()));
//                        }else{
//                            sbvMap.get(ib.getSubjectCode()).setBalanceDirection("贷");
//                            sbvMap.get(ib.getSubjectCode()).setBeginningBalance(0.0-a);
//                            sbvMap.get(ib.getSubjectCode()).setBalanceDirection("借");
//                        }
                        sbvMap.get(ib.getSubjectCode()).setBeginningDebitAmountNum(DoubleValueUtil.getNotNullVal(ib.getEndingDebitBalanceNum())-DoubleValueUtil.getNotNullVal(ib.getEndingCreditBalenceNum()));

                        sbvMap.get(ib.getSubjectCode()).setCurrencyBeginningBalance(DoubleValueUtil.getNotNullVal(ib.getCurrencyEndingDebitBalance())- DoubleValueUtil.getNotNullVal(ib.getCurrencyEndingCreditBalance()));

                    }else {
                        Double a = DoubleValueUtil.getNotNullVal(ib.getEndingCreditBalence())-DoubleValueUtil.getNotNullVal(ib.getEndingDebitBalance());
//                        if (a>=0){
                            sbvMap.get(ib.getSubjectCode()).setBeginningBalance(a);
//                        }else {
//                            sbvMap.get(ib.getSubjectCode()).setBalanceDirection("借");
//                            sbvMap.get(ib.getSubjectCode()).setBeginningBalance(0.0-a);
//                            sbvMap.get(ib.getSubjectCode()).setBalanceDirection("贷");
//                        }
                        sbvMap.get(ib.getSubjectCode()).setBeginningCreditAmountNum(DoubleValueUtil.getNotNullVal(ib.getEndingCreditBalenceNum())-DoubleValueUtil.getNotNullVal(ib.getEndingDebitBalanceNum()));
                        sbvMap.get(ib.getSubjectCode()).setCurrencyBeginningBalance(DoubleValueUtil.getNotNullVal(ib.getCurrencyEndingCreditBalance())- DoubleValueUtil.getNotNullVal(ib.getCurrencyEndingDebitBalance()));

                    }

                }
            });
        System.out.println("qichuhou"+sbvMap);
//        }else {
//            System.out.println("000000000000");
//            LambdaQueryWrapper<VoucherDetails> qwi = Wrappers.lambdaQuery();
//            qwi.eq(VoucherDetails::getAccountSetsId, accountSetsId);
////            qwi.in(VoucherDetails::getSubjectId, sbvMap.keySet());
//            qwi.isNull(VoucherDetails::getVoucherId);
//            qwi.and(wrapper -> {
//                wrapper.or(true).isNotNull(VoucherDetails::getCreditAmount);
//                wrapper.or(true).isNotNull(VoucherDetails::getDebitAmount);
//                return wrapper;
//            });
//            List<VoucherDetails> voucherDetails = this.voucherDetailsMapper.selectList(qwi);
//            voucherDetails.forEach(ib -> {
//                if (sbvMap.containsKey(ib.getSubjectCode())) {
//                    sbvMap.get(ib.getSubjectCode()).setBeginningBalance(DoubleValueUtil.getNotNullVal(ib.getCreditAmount(), ib.getDebitAmount()));
//                    sbvMap.get(ib.getSubjectCode()).setCurrencyBeginningBalance(DoubleValueUtil.getNotNullVal(ib.getCurrencyCredit(), ib.getCurrencyDebit()));
//
//                }
//            });
//            System.out.println("ppppppppppp");
//        }

//        System.out.println(sbvMap.keySet());
        System.out.println(subjectCodes);
        System.out.println(subjectIds);
        //本期发生额
        List<VoucherDetailVo> details = voucherMapper.selectSubjectDetailByParam1(subjectCodes, accountSetsId,startTime ,endTime, currencyId);
        details.forEach(vd -> {
            System.out.println("vdvdvdvd: " + vd);
            if (vd!=null){

                if (sbvMap.containsKey(vd.getSubjectCode())) {
                    BalanceVo sbv = sbvMap.get(vd.getSubjectCode());
                    sbv.setCurrentCreditAmount(vd.getCreditAmount());
                    sbv.setCurrentDebitAmount(vd.getDebitAmount());
                    sbv.setCurrencyCurrentCredit(vd.getCurrencyCredit());
                    sbv.setCurrencyCurrentDebit(vd.getCurrencyDebit());
                    System.out.println("---"+sbv);
                    if (showNumPrice && vd.getBalanceDirection() != null) {
                        System.out.println("-------------------------------");
//                        switch (vd.getBalanceDirection()) {
//                            case "借":
                                sbv.setCurrentDebitAmountNum(vd.getCumulativeDebitNum());
//                                break;
//                            case "贷":
                                sbv.setCurrentCreditAmountNum(vd.getCumulativeCreditNum());
//                                break;
//                        }
                    }
                }
            }

        });


        //计算期末
        List<BalanceVo> balanceVos = sbvMap.values().stream().sorted(Comparator.comparing(BalanceVo::getCode)).collect(Collectors.toList());
        BalanceVo aCombined1 = new BalanceVo();
        for (BalanceVo vo : balanceVos) {
            System.out.println(vo);
//            //期初
//            Double bb = DoubleValueUtil.getNotNullVal(vo.getBeginningBalance());
//            //外币期初
            Double currencyBeginningBalance = DoubleValueUtil.getNotNullVal(vo.getCurrencyBeginningBalance());
//            //本期借贷金额
//            Double cc = DoubleValueUtil.getNotNullVal(vo.getCurrentCreditAmount());
//            Double cd = DoubleValueUtil.getNotNullVal(vo.getCurrentDebitAmount());
            //外币本期借贷金额
            Double currencyCurrentCredit = DoubleValueUtil.getNotNullVal(vo.getCurrencyCurrentCredit());
            Double currencyCurrentDebit = DoubleValueUtil.getNotNullVal(vo.getCurrencyCurrentDebit());
            //本期借贷数量
//            Double openNum = DoubleValueUtil.getNotNullVal(vo.getBeginningCreditAmountNum(),vo.getBeginningDebitAmountNum());
//            Double ccNum = DoubleValueUtil.getNotNullVal(vo.getCurrentCreditAmountNum());
//            Double cdNum = DoubleValueUtil.getNotNullVal(vo.getCurrentDebitAmountNum());
            System.out.println(endTime+"  "+vo);
            InitBlanceVo initBlanceVoAmount = this.subjectMapper.selectEndingBalanceVo(accountSetsId, endTime ,vo.getCode(),currencyId);


            if (initBlanceVoAmount != null) {
                //根据方向计算余额
                switch (vo.getBalanceDirection()) {
                    case "借":
//                    System.out.println("vo_rtghjm: " + vo);
//                    System.out.println("bb: " + bb);
//                    System.out.println("cd: " + cd);
                    System.out.println(DoubleValueUtil.getNotNullVal(initBlanceVoAmount.getEndingDebitBalance())-DoubleValueUtil.getNotNullVal(initBlanceVoAmount.getEndingCreditBalence()));
//                    System.out.println("vo_endBalance: " + (bb + cd - cc));
                        vo.setEndingActiveBalance(DoubleValueUtil.getNotNullVal(initBlanceVoAmount.getEndingDebitBalance())-DoubleValueUtil.getNotNullVal(initBlanceVoAmount.getEndingCreditBalence()));
                        vo.setCurrencyEndingActiveBalance(currencyBeginningBalance + currencyCurrentDebit - currencyCurrentCredit);
                        vo.setEndingDebitBalanceNum(DoubleValueUtil.getNotNullVal(initBlanceVoAmount.getCumulativeDebitNum())-DoubleValueUtil.getNotNullVal(initBlanceVoAmount.getCumulativeCreditNum()));
                        break;
                    case "贷":
                        System.out.println(DoubleValueUtil.getNotNullVal(initBlanceVoAmount.getEndingCreditBalence())-DoubleValueUtil.getNotNullVal(initBlanceVoAmount.getEndingDebitBalance()));

                        vo.setEndingActiveBalance(DoubleValueUtil.getNotNullVal(initBlanceVoAmount.getEndingCreditBalence())-DoubleValueUtil.getNotNullVal(initBlanceVoAmount.getEndingDebitBalance()));
                        vo.setCurrencyEndingActiveBalance(currencyBeginningBalance - currencyCurrentDebit + currencyCurrentCredit);
                        vo.setEndingCreditBalanceNum(DoubleValueUtil.getNotNullVal(initBlanceVoAmount.getCumulativeCreditNum())-DoubleValueUtil.getNotNullVal(initBlanceVoAmount.getCumulativeDebitNum()));

                        break;
                }
            }



//            if (showNumPrice) {
////                System.out.println(vo.getName()+openNum +"---"+ cdNum +"---"+ ccNum);
//                switch (vo.getBalanceDirection()) {
//                    case "借":
//                        vo.setEndingDebitBalanceNum(openNum + cdNum - ccNum);
//                        break;
//                    case "贷":
//                        vo.setEndingCreditBalanceNum(openNum + ccNum - cdNum);
//                        break;
//                }
//            }
            //计算合计列
//            aCombined.setBeginningCreditBalance(vo.getBeginningCreditBalance());
//            aCombined.setBeginningDebitBalance(vo.getBeginningDebitBalance());
//
//            //外币期初借贷方余额
//            aCombined.setCurrencyBeginningCreditBalance(vo.getCurrencyBeginningCreditBalance());
//            aCombined.setCurrencyBeginningDebitBalance(vo.getCurrencyBeginningDebitBalance());
//
//            aCombined.setCurrentCreditAmount(vo.getCurrentCreditAmount());
//            aCombined.setCurrentCreditAmountNum(vo.getCurrentCreditAmountNum());
//            aCombined.setCurrentDebitAmount(vo.getCurrentDebitAmount());
//            aCombined.setCurrentDebitAmountNum(vo.getCurrentDebitAmountNum());
//
//            //外币本期发生额
//            aCombined1.setCurrencyCurrentCredit(vo.getCurrencyCurrentCredit());
//            aCombined1.setCurrencyCurrentDebit(vo.getCurrencyCurrentDebit());
//
//            if (vo.getLevel()==1){
//                aCombined1.setEndingCreditBalance(vo.getEndingCreditBalance());
//                aCombined1.setEndingCreditBalanceNum(vo.getEndingCreditBalanceNum());
//                aCombined1.setEndingDebitBalance(vo.getEndingDebitBalance());
//                aCombined1.setEndingDebitBalanceNum(vo.getEndingDebitBalanceNum());
////
////            //外币期末借贷方余额
//                aCombined1.setCurrencyEndingCreditBalance(vo.getCurrencyEndingCreditBalance());
//                aCombined1.setCurrencyEndingDebitBalance(vo.getCurrencyEndingDebitBalance());
//                System.out.println(aCombined1+"000000000000000000000000000000000000000");
//            }

        }
        //合计
        BalanceVo aCombined = new BalanceVo();
        aCombined.setName("合计");
//        List<BalanceVo> initAcombined = this.subjectMapper.selectInitAcombined(accountSetsId, startTime ,subjectIds);
//        List<BalanceVo> currcentAcombined = this.subjectMapper.selectCurrcentAcombined(accountSetsId, startTime ,endTime ,subjectIds);
//        List<BalanceVo> endAcombined = this.subjectMapper.selectEndAcombined(accountSetsId, endTime ,subjectIds);
//        Double a1 = 0d,a2 = 0d,a3 = 0d,a4 = 0d,a5 = 0d,a6 = 0d;
//        Double b1 = 0d,b2 = 0d,b3 = 0d,b4 = 0d,b5 = 0d,b6 = 0d;
//        Double c1 = 0d,c2 = 0d,c3 = 0d,c4 = 0d,c5 = 0d,c6 = 0d;
//        for (int i = 0; i < initAcombined.size(); i++) {
//            if (initAcombined.get(i) != null) {
//                a1 = DoubleValueUtil.getNotNullVal(initAcombined.get(i).getBeginningCreditBalance()) + a1;
//                a2 = DoubleValueUtil.getNotNullVal(initAcombined.get(i).getBeginningDebitBalance()) + a2;
//                a3 = DoubleValueUtil.getNotNullVal(initAcombined.get(i).getBeginningCreditAmountNum()) + a3;
//                a4 = DoubleValueUtil.getNotNullVal(initAcombined.get(i).getBeginningDebitAmountNum()) + a4;
//                a5 = DoubleValueUtil.getNotNullVal(initAcombined.get(i).getCurrencyBeginningCreditBalance()) + a5;
//                a6 = DoubleValueUtil.getNotNullVal(initAcombined.get(i).getCurrencyBeginningDebitBalance()) + a6;
//            }
//        }
//        for (int i = 0; i < currcentAcombined.size(); i++) {
//            if (currcentAcombined.get(i) != null) {
//                b1 = DoubleValueUtil.getNotNullVal(currcentAcombined.get(i).getCurrentCreditAmount()) + b1;
//                b2 = DoubleValueUtil.getNotNullVal(currcentAcombined.get(i).getCurrentDebitAmount()) + b2;
//                b3 = DoubleValueUtil.getNotNullVal(currcentAcombined.get(i).getCurrentCreditAmountNum()) + b3;
//                b4 = DoubleValueUtil.getNotNullVal(currcentAcombined.get(i).getCurrentDebitAmountNum()) + b4;
//                b5 = DoubleValueUtil.getNotNullVal(currcentAcombined.get(i).getCurrencyCurrentCredit()) + b5;
//                b6 = DoubleValueUtil.getNotNullVal(currcentAcombined.get(i).getCurrencyCurrentDebit()) + b6;
//            }
//        }
//        for (int i = 0; i < endAcombined.size(); i++) {
//            if (endAcombined.get(i) != null) {
//                c1 = DoubleValueUtil.getNotNullVal(endAcombined.get(i).getEndingCreditBalance()) + c1;
//                c2 = DoubleValueUtil.getNotNullVal(endAcombined.get(i).getEndingCreditBalanceNum()) + c2;
//                c3 = DoubleValueUtil.getNotNullVal(endAcombined.get(i).getEndingDebitBalance()) + c3;
//                c4 = DoubleValueUtil.getNotNullVal(endAcombined.get(i).getEndingDebitBalanceNum()) + c4;
//                c5 = DoubleValueUtil.getNotNullVal(endAcombined.get(i).getCurrencyEndingCreditBalance()) + c5;
//                c6 = DoubleValueUtil.getNotNullVal(endAcombined.get(i).getCurrencyEndingDebitBalance()) + c6;
//            }
//        }
        //计算合计列期初额
//        System.out.println(a1+"=---------------"+a2);
//        aCombined.setBeginningCreditBalance(a1);
//        aCombined.setBeginningDebitBalance(a2);
//        aCombined.setBeginningCreditAmountNum(a3);
//        aCombined.setBeginningDebitAmountNum(a4);
//        aCombined.setCurrencyBeginningCreditBalance(a5);
//        aCombined.setCurrencyBeginningDebitBalance(a6);
//        //本期发生额
//        aCombined.setCurrentCreditAmount(b1);
//        aCombined.setCurrentDebitAmount(b2);
//        aCombined.setCurrentCreditAmountNum(b3);
//        aCombined.setCurrentDebitAmountNum(b4);
//        aCombined.setCurrencyCurrentCredit(b5);
//        aCombined.setCurrencyCurrentDebit(b6);
        //期末余额
//        aCombined.setEndingCreditBalance(aCombined1.getEndingCreditBalance());
//        aCombined.setEndingCreditBalanceNum(aCombined1.getEndingCreditBalanceNum());
//        aCombined.setEndingDebitBalance(aCombined1.getEndingDebitBalance());
//        aCombined.setEndingDebitBalanceNum(aCombined1.getEndingDebitBalanceNum());
//        aCombined.setCurrencyEndingCreditBalance(aCombined1.getCurrencyEndingCreditBalance());
//        aCombined.setCurrencyEndingDebitBalance(aCombined1.getCurrencyEndingDebitBalance());

//        System.out.println(initAcombined);
            //计算父节点
//            for (int i = balanceVos.size() - 1; i > 0; i--) {
//                BalanceVo vo = balanceVos.get(i);
//
//                if (vo.getLevel() != 1) {
//
//                    Subject s = this.baseMapper.selectById(vo.getParentId());
//                    if(s == null){
//                        continue;
//                    }
//                    BalanceVo parent = sbvMap.get(s.getCode());
//                    if (parent != null) {
//                        if(initBlanceVos.size() == 0) {
//                            parent.setBeginningBalance(vo.getBeginningBalance());
//                            parent.setCurrentDebitAmount(vo.getCurrentDebitAmount());
//                            parent.setCurrentDebitAmountNum(vo.getCurrentDebitAmountNum());
//                            parent.setCurrentCreditAmount(vo.getCurrentCreditAmount());
//                            parent.setCurrentCreditAmountNum(vo.getCurrentCreditAmountNum());
//
//                            //外币
//                            parent.setCurrencyBeginningBalance(vo.getCurrencyBeginningBalance());
//                            parent.setCurrencyCurrentDebit(vo.getCurrencyCurrentDebit());
//                            parent.setCurrencyCurrentCredit(vo.getCurrencyCurrentCredit());
//
//                            if(vo.getBalanceDirection().equals("借")){
////                                parent.setEndingDebitBalance(
////                                        DoubleValueUtil.getNotNullVal(vo.getBeginningBalance())
////                                                +
////                                                DoubleValueUtil.getNotNullVal(vo.getCurrentDebitAmount())
////                                                -
////                                                DoubleValueUtil.getNotNullVal(vo.getCurrentCreditAmount()));
//
//                                parent.setCurrencyEndingDebitBalance(
//                                        DoubleValueUtil.getNotNullVal(vo.getCurrencyBeginningBalance())
//                                                +
//                                                DoubleValueUtil.getNotNullVal(vo.getCurrencyCurrentDebit())
//                                                -
//                                                DoubleValueUtil.getNotNullVal(vo.getCurrencyCurrentCredit()));
//                            }else {
////                                parent.setEndingCreditBalance(
////                                        DoubleValueUtil.getNotNullVal(vo.getBeginningBalance())
////                                                -
////                                                DoubleValueUtil.getNotNullVal(vo.getCurrentDebitAmount())
////                                                +
////                                                DoubleValueUtil.getNotNullVal(vo.getCurrentCreditAmount()));
//
//                                parent.setCurrencyEndingCreditBalance(
//                                        DoubleValueUtil.getNotNullVal(vo.getCurrencyBeginningBalance())
//                                                -
//                                                DoubleValueUtil.getNotNullVal(vo.getCurrencyCurrentDebit())
//                                                +
//                                                DoubleValueUtil.getNotNullVal(vo.getCurrencyCurrentCredit()));
//                            }
//                        }else {
//                            parent.setCurrentDebitAmount(vo.getCurrentDebitAmount());
//                            parent.setCurrentDebitAmountNum(vo.getCurrentDebitAmountNum());
//                            parent.setCurrentCreditAmount(vo.getCurrentCreditAmount());
//                            parent.setCurrentCreditAmountNum(vo.getCurrentCreditAmountNum());
////                            parent.setEndingDebitBalance(0.0,1);
//
//                            //外币
//                            parent.setCurrencyCurrentDebit(vo.getCurrencyCurrentDebit());
//                            parent.setCurrencyCurrentCredit(vo.getCurrencyCurrentCredit());
//                            parent.setCurrencyEndingDebitBalance(0.0,1);
//                            if(vo.getBalanceDirection().equals("借")){
////                                parent.setEndingDebitBalance(
////                                        DoubleValueUtil.getNotNullVal(parent.getBeginningBalance())
////                                                +
////                                                DoubleValueUtil.getNotNullVal(vo.getCurrentDebitAmount())
////                                                -
////                                                DoubleValueUtil.getNotNullVal(vo.getCurrentCreditAmount()));
//
//                                parent.setCurrencyEndingDebitBalance(
//                                        DoubleValueUtil.getNotNullVal(parent.getCurrencyBeginningBalance())
//                                                +
//                                                DoubleValueUtil.getNotNullVal(vo.getCurrencyCurrentDebit())
//                                                -
//                                                DoubleValueUtil.getNotNullVal(vo.getCurrencyCurrentCredit()));
//                            }else {
////                                parent.setEndingCreditBalance(
////                                        DoubleValueUtil.getNotNullVal(parent.getBeginningBalance())
////                                                -
////                                                DoubleValueUtil.getNotNullVal(vo.getCurrentDebitAmount())
////                                                +
////                                                DoubleValueUtil.getNotNullVal(vo.getCurrentCreditAmount()));
//
//                                parent.setCurrencyEndingCreditBalance(
//                                        DoubleValueUtil.getNotNullVal(parent.getCurrencyBeginningBalance())
//                                                -
//                                                DoubleValueUtil.getNotNullVal(vo.getCurrencyCurrentDebit())
//                                                +
//                                                DoubleValueUtil.getNotNullVal(vo.getCurrencyCurrentCredit()));
//                            }
//                        }
//
////                    if (vo.getEndingCreditBalance() != null) {
////                        parent.setEndingCreditBalance(vo.getEndingCreditBalance());
////                    }
////                    if (vo.getEndingDebitBalance() != null) {
////                        parent.setEndingDebitBalance(vo.getEndingDebitBalance());
////                    }
//                    }
//                }
//            }


        System.out.println("-----"+balanceVos);
        if (balanceVos.size() > 0) {
            //过滤掉空行
            balanceVos = balanceVos.stream().filter(vo ->
                            (vo.getBeginningBalance() != null && vo.getBeginningBalance() != 0) ||
                            (vo.getEndingBalance() != null && vo.getEndingBalance() != 0) ||
                            (vo.getCurrentDebitAmount() != null && vo.getCurrentDebitAmount() != 0) ||
                            (vo.getCurrentCreditAmount() != null && vo.getCurrentCreditAmount() != 0) ||

                                    //外币
                            (vo.getCurrencyBeginningBalance() != null && vo.getCurrencyBeginningBalance() != 0) ||
                            (vo.getCurrencyEndingBalance() != null && vo.getCurrencyEndingBalance() != 0) ||
                            (vo.getCurrencyCurrentDebit() != null && vo.getCurrencyCurrentDebit() != 0) ||
                            (vo.getCurrencyCurrentCredit() != null && vo.getCurrencyCurrentCredit() != 0)
            ).collect(Collectors.toList());
        }
        List<BalanceVo> remove = new ArrayList<>();
        balanceVos.forEach(balanceVo ->{
            if(balanceVo.getIsAuxiliary() != null && balanceVo.getIsAuxiliary() == 1){
                remove.add(balanceVo);
            }
        });
        balanceVos.removeAll(remove);
        balanceVos.forEach(vos ->{
            System.out.println(vos);
            if (vos.getLevel().equals(levelMin)){
                aCombined.setBeginningCreditBalance(vos.getBeginningCreditBalance());
                aCombined.setBeginningDebitBalance(vos.getBeginningDebitBalance());
                aCombined.setBeginningCreditAmountNum(vos.getBeginningCreditAmountNum());
                aCombined.setBeginningDebitAmountNum(vos.getBeginningDebitAmountNum());
                aCombined.setCurrencyBeginningCreditBalance(vos.getCurrencyBeginningCreditBalance());
                aCombined.setCurrencyBeginningDebitBalance(vos.getCurrencyBeginningDebitBalance());
                //本期发生额
                aCombined.setCurrentCreditAmount(vos.getCurrentCreditAmount());
                aCombined.setCurrentDebitAmount(vos.getCurrentDebitAmount());
                aCombined.setCurrentCreditAmountNum(vos.getCurrentCreditAmountNum());
                aCombined.setCurrentDebitAmountNum(vos.getCurrentDebitAmountNum());
                aCombined.setCurrencyCurrentCredit(vos.getCurrencyCurrentCredit());
                aCombined.setCurrencyCurrentDebit(vos.getCurrencyCurrentDebit());

                aCombined.setEndingCreditBalance(vos.getEndingCreditBalance());
                aCombined.setEndingCreditBalanceNum(vos.getEndingCreditBalanceNum());
                aCombined.setEndingDebitBalance(vos.getEndingDebitBalance());
                aCombined.setEndingDebitBalanceNum(vos.getEndingDebitBalanceNum());
//
//            //外币期末借贷方余额
                aCombined.setCurrencyEndingCreditBalance(vos.getCurrencyEndingCreditBalance());
                aCombined.setCurrencyEndingDebitBalance(vos.getCurrencyEndingDebitBalance());
                System.out.println(aCombined+"000000000000000000000000000000000000000");
            }
        });
        balanceVos.add(aCombined);
        return balanceVos;
    }



    List<Subject> selectAccountList(String startTime,String endTime ,String startSubject, String endSubject, Integer startLevel, Integer endLevel,Integer accountSetsId,boolean isOpen,boolean showNumPrice,Integer currencyId){
        List<Subject> subjectList = baseMapper.selectAccountSubjectListByParam(startTime, endTime, startSubject, endSubject, startLevel, endLevel, accountSetsId,showNumPrice,currencyId);
//        return subjectList;
//          if(!isOpen){ //是否开启 查询 科目的 父科目
//          return subjectList;
//        }
        Map<String, Subject> temp = new HashMap<>();
        subjectList.forEach(subject -> this.recursiveParent2(temp, subject));
        return temp.values().stream().sorted(Comparator.comparing(Subject::getCode)).distinct().collect(Collectors.toList());
//        return subjectList;
    }




    /**
     * 科目汇总
     *
     * @param accountDate
     * @param accountSetsId
     * @return
     */
    @Override
    public List subjectSummary(Date startTime,Date endTime,Integer accountSetsId, boolean showNumPrice, Integer currencyId) {
        List<Subject> subjects = this.accountBookListCurrency(startTime,endTime, accountSetsId, showNumPrice ,currencyId);
        subjects = recursiveSubjectBalance(subjects);
        //转换为余额对象
        Map<Integer, BalanceVo> sbvMap = subjects.stream().collect(Collectors.toMap(Subject::getId, subject -> {
            BalanceVo sbv = new BalanceVo();
            if (currencyId != -1 && currencyId != -2){
                sbv.setCurrencyCode(baseMapper.selectCurrencyCode(subject.getId()));
            }
            sbv.setSubjectId(subject.getId());
            sbv.setCode(subject.getCode());
            sbv.setUnit(subject.getUnit());
            sbv.setParentId(subject.getParentId());
            sbv.setName(subject.getName());
            sbv.setLevel(subject.getLevel());
            sbv.setBalanceDirection(subject.getBalanceDirection().toString());
            return sbv;
        }));

        if (sbvMap.isEmpty()) {
            return new ArrayList<>();
        }

        //本期发生额
        List<VoucherDetailCurrencyVo> details = voucherMapper.selectSubjectDetailByCurrency(sbvMap.keySet(), accountSetsId,startTime,endTime, showNumPrice);
        System.out.println("1111"+details);
        details.forEach(vd -> {
            if (sbvMap.containsKey(vd.getSubjectId())) {
                BalanceVo sbv = sbvMap.get(vd.getSubjectId());
                if (showNumPrice) {
                    if (vd.getBalanceDirection() != null) {
                        switch (vd.getBalanceDirection()) {
                            case "借":
                                sbv.setCurrentDebitAmount(vd.getDebitAmount());
                                sbv.setCurrencyDebitAmount(vd.getCurrencyDebit());
                                sbv.setCurrentDebitAmountNum(vd.getNum());
                                break;
                            case "贷":
                                sbv.setCurrentCreditAmount(vd.getCreditAmount());
                                sbv.setCurrencyCreditAmount(vd.getCurrencyCredit());
                                sbv.setCurrentCreditAmountNum(vd.getNum());
                                break;
                        }
                    }
                } else {
                    sbv.setCurrentCreditAmount(vd.getCreditAmount());
                    sbv.setCurrentDebitAmount(vd.getDebitAmount());
                    sbv.setCurrencyCreditAmount(vd.getCurrencyCredit());
                    sbv.setCurrencyDebitAmount(vd.getCurrencyDebit());
                }
            }
        });
        System.out.println("2222"+details);
        //合计
        BalanceVo aCombined = new BalanceVo();
        if (details.size() != 0){
            aCombined.setCurrencyCode(details.get(0).getCurrencyCode());
        }
        aCombined.setName("合计");
        //计算期末
        List<BalanceVo> balanceVos = sbvMap.values().stream().sorted(Comparator.comparing(BalanceVo::getCode)).collect(Collectors.toList());
        System.out.println(balanceVos);
        for (BalanceVo vo : balanceVos) {
            aCombined.setCurrentCreditAmount(vo.getCurrentCreditAmount());
            aCombined.setCurrentCreditAmountNum(vo.getCurrentCreditAmountNum());
            aCombined.setCurrentDebitAmount(vo.getCurrentDebitAmount());
            aCombined.setCurrentDebitAmountNum(vo.getCurrentDebitAmountNum());
            aCombined.setCurrencyCreditAmount(vo.getCurrencyCreditAmount());
            aCombined.setCurrencyDebitAmount(vo.getCurrencyDebitAmount());
        }

        //计算父节点
        for (int i = balanceVos.size() - 1; i > 0; i--) {
            BalanceVo vo = balanceVos.get(i);
            if (vo.getLevel() != 1) {
                BalanceVo parent = sbvMap.get(vo.getParentId());
                if (parent != null) {
                    parent.setCurrentDebitAmount(vo.getCurrentDebitAmount());
                    parent.setCurrentDebitAmountNum(vo.getCurrentDebitAmountNum());
                    parent.setCurrentCreditAmount(vo.getCurrentCreditAmount());
                    parent.setCurrentCreditAmountNum(vo.getCurrentCreditAmountNum());
                    parent.setCurrencyCreditAmount(vo.getCurrencyCreditAmount());
                    parent.setCurrencyDebitAmount(vo.getCurrencyDebitAmount());
                }
            }
        }

        if (balanceVos.size() > 0) {
            balanceVos.add(aCombined);
        }

        return balanceVos;
    }

    private void recursiveParent(Map<Integer, Subject> temp, Subject subject) {
        if (subject!=null){
            temp.put(subject.getId(), subject);
            if (subject.getLevel() != 1) {
                if (!temp.containsKey(subject.getParentId())) {
                    Subject sbj = baseMapper.selectById(subject.getParentId());
                    this.recursiveParent(temp, sbj);
                }
            }
        }
    }

    private void recursiveParentByMX(Map<Integer, Subject> temp, Subject subject) {
        System.out.println(subject);
        if (subject!=null){
            temp.put(subject.getId(), subject);
            if (subject.getLevel() != 1) {
                if (!temp.containsKey(subject.getParentId())) {
                    Subject sbj = baseMapper.selectById(subject.getParentId());
                    System.out.println("==="+sbj);
                    if (subject.getUnit()!=null&&!subject.getUnit().equals("")){
                        sbj.setUnit("null");
                    }
                    this.recursiveParentByMX(temp, sbj);
                }
            }
        }
    }

    private List<Subject> recursiveSubjectBalance(List<Subject> subjects) {
        List<Integer> subjectIds = new ArrayList<>();
        for (int i = 0; i < subjects.size(); i++) {
            if (subjects.get(i).getParentId()!=null && !subjects.get(i).getParentId().equals(0) && subjects.get(i).getUnit()!=null && !subjects.get(i).getUnit().equals("")){
                subjectIds.add(subjects.get(i).getParentId());
            }
        }
        if (subjectIds.size()>0){
            for (int i = 0; i < subjects.size(); i++) {
                for (int j = 0; j < subjectIds.size(); j++) {
                    if (subjects.get(i).getId().equals(subjectIds.get(j))){
                        subjects.get(i).setUnit("null");
                    }
                }
            }
        }
        return subjects;
    }




    private void recursiveParent2(Map<String, Subject> temp, Subject subject) {
        if (subject!=null){
            temp.put(subject.getCode(), subject);
            if (subject.getLevel() != 1) {
                if (!temp.containsKey(subject.getCode().substring(0,4))) {
                    Subject sbj = baseMapper.selectById(subject.getParentId());
                    this.recursiveParent2(temp, sbj);
                }
            }
        }
    }


    private void recursiveChildren(Map<Integer, Subject> subjectMap, Subject subject, int parentId) {

        Subject parent = subjectMap.get(parentId);
        subject.setName(parent.getName() + "-" + subject.getName());
        if (parent.getLevel() != 1) {
            recursiveChildren(subjectMap, subject, parent.getParentId());
        }
    }

    @Override
    public List<SubjectVo> listVo(Wrapper<Subject> queryWrapper) {
        QueryWrapper<Subject> qw = (QueryWrapper<Subject>) queryWrapper;
        qw.orderByAsc("code");
        return baseMapper.selectSubjectVo(queryWrapper);
    }

    /**
     * 检查科目是否已经被使用
     *
     * @param id
     * @return
     */
    @Override
    public Boolean checkUse(Integer id) {
        LambdaQueryWrapper<VoucherDetails> vdqw = Wrappers.lambdaQuery();
        vdqw.eq(VoucherDetails::getSubjectId, id);
//        vdqw.isNotNull(VoucherDetails::getVoucherId);//ywh新建的一行
        boolean vd = voucherDetailsMapper.selectCount(vdqw) == 0;
        LambdaQueryWrapper<VoucherTemplateDetails> vtdqw = Wrappers.lambdaQuery();
        vtdqw.eq(VoucherTemplateDetails::getSubjectId, id);
        boolean vtd = voucherTemplateDetailsMapper.selectCount(vtdqw) == 0;
        System.out.println(voucherDetailsMapper.selectCount(vdqw));
        System.out.println(voucherTemplateDetailsMapper.selectCount(vtdqw));
        return !(vd && vtd);
    }

    /**
     * 科目余额
     *
     * @param accountSetsId
     * @param subjectId
     * @param categoryId
     * @param categoryDetailsId
     * @return
     */
    @Override
    public Double balance(Integer accountSetsId, Integer subjectId, Integer categoryId, Integer categoryDetailsId) {
        LambdaQueryWrapper<VoucherDetails> ibqw = Wrappers.lambdaQuery();
        ibqw.eq(VoucherDetails::getSubjectId, subjectId);
        ibqw.eq(VoucherDetails::getAccountSetsId, accountSetsId);
        ibqw.isNull(VoucherDetails::getVoucherId);

        List<VoucherDetails> ibs = this.voucherDetailsMapper.selectList(ibqw);
        VoucherDetails ib = null;
        if (ibs.size() > 0) {
            ib = ibs.get(0);
            for (int i = 1; i < ibs.size(); i++) {
                double creditAmount = Optional.ofNullable(ib.getCreditAmount()).orElse(0d) + Optional.ofNullable(ibs.get(i).getCreditAmount()).orElse(0d);
                double debitAmount = Optional.ofNullable(ib.getDebitAmount()).orElse(0d) + Optional.ofNullable(ibs.get(i).getDebitAmount()).orElse(0d);
                ib.setCreditAmount(creditAmount);
                ib.setDebitAmount(debitAmount);
            }
        }


        List<VoucherDetailVo> vds = voucherDetailsMapper.selectBalanceData(accountSetsId, subjectId, categoryId, categoryDetailsId);
        double balance = 0d;
        if (!vds.isEmpty()) {
            VoucherDetailVo vo = vds.get(0);
            if (vo != null) {
                if (vo.getBalanceDirection().equals("借")) {
                    balance = DoubleValueUtil.getNotNullVal(vo.getDebitAmount()) - DoubleValueUtil.getNotNullVal(vo.getCreditAmount());
                } else {
                    balance = DoubleValueUtil.getNotNullVal(vo.getCreditAmount()) - DoubleValueUtil.getNotNullVal(vo.getDebitAmount());
                }
            }
        }

        //TODO 期初暂时没有辅助期初，categoryId == null过滤掉辅助
        if (ib != null && categoryId == null) {
            balance += DoubleValueUtil.getNotNullVal(ib.getDebitAmount(), ib.getCreditAmount());
        }

        return balance;
    }




    /**
     * 科目余额
     *
     * @param accountSetsId
     * @param subjectId
     * @return
     */
    @Override
    public Double balance2(Integer accountSetsId, Integer subjectId, String auxiliaryTitle,List<CategoryVo> categoryVoList) {
        System.out.println("qqqq");
        List<VoucherDetails> ibs = voucherDetailsMapper.selectQichu(accountSetsId,subjectId,categoryVoList);
        VoucherDetails ib = null;
        for (VoucherDetails voucherDetails : ibs) {
            if (voucherDetails.getCountNum() == categoryVoList.size()){
                ib =voucherDetails;
            }
        }
        List<VoucherDetailVo> vds = voucherDetailsMapper.selectBalanceData1(accountSetsId, subjectId,auxiliaryTitle);
        double balance = 0d;
        if (!vds.isEmpty()) {
            VoucherDetailVo vo = vds.get(0);
            if (vo != null) {
                if (vo.getBalanceDirection().equals("借")) {
                    balance = DoubleValueUtil.getNotNullVal(vo.getDebitAmount()) - DoubleValueUtil.getNotNullVal(vo.getCreditAmount());
                } else {
                    balance = DoubleValueUtil.getNotNullVal(vo.getCreditAmount()) - DoubleValueUtil.getNotNullVal(vo.getDebitAmount());
                }
            }
        }

        //TODO 期初暂时没有辅助期初，categoryId == null过滤掉辅助
        if (ib != null) {
            balance += DoubleValueUtil.getNotNullVal(ib.getDebitAmount(), ib.getCreditAmount());
        }

        return balance;
    }






    /**
     * 过滤出所有没有子节点的科目
     *
     * @param accountSetsId
     * @return
     */
    @Override
    public List<Integer> leafList(Integer accountSetsId) {
        return this.baseMapper.selectLeaf(accountSetsId);
    }

    @Override
    public HashMap<String,String> subjectSave(Subject entity) {
        LambdaQueryWrapper<Subject> qw = Wrappers.lambdaQuery();
        qw.eq(Subject::getAccountSetsId, entity.getAccountSetsId());
        qw.eq(Subject::getName, entity.getName());
        if(entity.getParentId()==null){
            qw.isNull(Subject::getParentId);
        }else {
            qw.eq(Subject::getParentId, entity.getParentId());
        }
        HashMap<String, String> hashMap = new HashMap<>();
        if (this.count(qw) > 0) {
            hashMap.put("false","科目名称已经存在！");
            return hashMap;
//            throw new ServiceException("科目名称已经存在！");
        }

        qw = Wrappers.lambdaQuery();
        qw.eq(Subject::getAccountSetsId, entity.getAccountSetsId());
        qw.eq(Subject::getCode, entity.getCode());

        if (this.count(qw) > 0) {
            hashMap.put("false","科目编码已经存在！");
            return hashMap;
//            throw  new ServiceException("科目编码已经存在！");
        }
        boolean save = super.save(entity);
        hashMap.put(String.valueOf(save),"创建完成");
        return hashMap;
    }

    @Override
    public boolean remove(Wrapper<Subject> wrapper) {
        if (this.checkUse(getOne(wrapper).getId())) {
            throw  new ServiceException("科目已被使用，不能删除！");
        }
        return super.remove(wrapper);
    }

    public static void main(String[] args) {
        String a = "2221102";
        System.out.println(a.substring(0,4));
    }
}